package org.wizehack.mri.testSet;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.wizehack.mri.CoverageDataParser.CoverageFileReader;
import org.wizehack.mri.CoverageDataParser.SourceFile;
import org.wizehack.mri.exception.InvalidFileExtensionException;
import org.wizehack.mri.exception.ObjectNotFoundException;
import org.wizehack.mri.io.FileCopy;
import org.wizehack.mri.io.FileListReader;
import org.wizehack.mri.test.BasicTestCase;
import org.wizehack.mri.test.TestCase;
import org.wizehack.mri.test.TestSuite;

public abstract class TestCaseReduction implements TestCaseSelection {
	private TestSuite testSuite;
	private List<String> failedCoverageFileList;
	private static String directory;

	/**
	 * this method searches coverage files (*.xml) in the given directory path
	 * @param dirPath directory path
	 * @return the list that includes the name of files
	 */
	protected List<String> scanCoverageFile(String dirPath){
		FileListReader fileListReader = new FileListReader();
		List<String> fList = fileListReader.readFiles(new File(dirPath));
		
		return fList;
	}
	
	/**
	 * getter of the directory that includes files(*.xml) that have code coverage data.
	 * @return
	 */
	public String getDirectory(){
		return this.directory;
	}
	
	/**
	 * setter of the directory that includes files(*.xml) that have code coverage data.
	 * @return
	 */
	public void setDirectory(String directory){
		this.directory = directory;
	}
	
	/**
	 * getter for the instance of TestSuite
	 * @return
	 */
	public TestSuite getTestSuite() {
		return testSuite;
	}
	
	/**
	 * setter for the instance of TestSuite
	 * @param testSuite
	 */
	public void setTestSuite(TestSuite testSuite) {
		this.testSuite = testSuite;
	}
	
	/**
	 * this method adds the given test case to the test suite that is defined by setTestSuite method. 
	 * @param testCase 
	 */
	protected void addTestCase(TestCase testCase){
		if(this.testSuite.contains(testCase) == false){
			this.testSuite.add(testCase);
		}
	}
	
	/**
	 * this method adds the given test case from the test suite that is defined by setTestSuite method. 
	 * @param testCase
	 * @return return true if the test case are removed, return false if the test case are not removed
	 */
	protected boolean removeTestCase(TestCase testCase){

		if(this.testSuite.contains(testCase)){
			return testSuite.remove(testCase);	
		} else {
			try {
				throw (new ObjectNotFoundException(testCase));
			} catch (ObjectNotFoundException e) {
				e.printStackTrace();
			}
			return false;
		}
	}
	
	/**
	 * This method returns the coverage of the given test case. 
	 * @param testCase
	 * @return
	 */
	protected List<SourceFile> getCoveredLine(TestCase testCase){
		File tcLocaction = new File(testCase.getCoverageLocation());
		CoverageFileReader cfr = new CoverageFileReader(tcLocaction);
		
		List <SourceFile> coverage = cfr.getCoverage();
		
		for(int i=0; i<coverage.size(); i++){
			SourceFile sf = coverage.get(i);
					
			for(int j=0; j<sf.size(); j++){
				if(sf.get(j).isCovered()==false){
					sf.remove(j);
				}
			}
		}
		
		return coverage;
	}

	
	protected boolean isEquivalent(TestCase tc1, TestCase tc2){
		
		boolean isEquivalent = true;
		
		/* covered statements 만 비교 */
		List<SourceFile> coverage1 = this.getCoveredLine(tc1);
		List<SourceFile> coverage2 = this.getCoveredLine(tc2);
		
		if(coverage1.size() == coverage2.size()){
			
			for(int i=0; i<coverage1.size() && isEquivalent == true; i++){
				SourceFile sFile1 = coverage1.get(i);
				String fileName1 = sFile1.getName();
				
				for(int j=0; j<coverage2.size() && isEquivalent == true; j++){
					SourceFile sFile2 = coverage2.get(j);
					
					if(fileName1.equals(sFile2.getName())){
						
						for(int k=0; k<sFile1.size() && k<sFile2.size(); k++){
							
							if(sFile1.get(k).getLineNumber() != sFile2.get(k).getLineNumber()){
								isEquivalent = false;
								break;
							}
						}
					} else if(isEquivalent == false){
						break;
					}
					
				}// for j
			}// for i
		}
		
		return isEquivalent;
	}
	
	
	public List<String> getFailedCoverageFileList() {
		return failedCoverageFileList;
	}

	public void setFailedCoverageFileList(List<String> failedCoverageFileList) {
		this.failedCoverageFileList = failedCoverageFileList;
	}
	
	public TestSuite setTestResult(List<String> coverageFileList, List<String> failedCoverageFileList) {
		for(int i=0; i<coverageFileList.size(); i++){
			TestCase testCase = new BasicTestCase();
			testCase.setTcId(i);
			
			String coverageFile = coverageFileList.get(i);
			testCase.setCoverageLocation(coverageFile);
			List<SourceFile> coverage = this.getCoveredLine(testCase);
			testCase.setCoverage(coverage);
			
			if(failedCoverageFileList != null && failedCoverageFileList.contains(coverageFile))
				testCase.setPassed(false);		
			else
				testCase.setPassed(true);
			
			this.addTestCase(testCase);
		}
		
		return this.testSuite;
	}
	
	public void exportTo(TestSuite testSuite, String destDir, String dtdFile) throws InvalidFileExtensionException{
		FileCopy fcopy = new FileCopy();
		File dtd = new File(dtdFile);
				
		if(dtdFile.lastIndexOf(".dtd")>0){
			String destDTD = destDir + File.separator + dtd.getName();
			try {
				fcopy.copy(dtdFile, destDTD);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		} else {
			throw new InvalidFileExtensionException(dtdFile);
		}
		
		for(int i=0; i<testSuite.size(); i++){
			String xmlFile = testSuite.get(i).getCoverageLocation();
			
			File file = new File(xmlFile);
			String destFile = destDir + file.separator + file.getName();
			
			try {
				fcopy.copy(xmlFile, destFile);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	} 
}
